<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="fr" xml:lang="fr">
<head>
	<title>TzParser : Documentation EN</title>

	<style type="text/css">
		*
		{
			padding: 0;
			margin: 0;
		}
		
		body
		{
			font-family: Verdana, sans-serif;
			font-size: 13px;
			background-color: black;
			color: white;
			padding: 10px;
			width: 884px;
			margin: 10px auto;
			border: solid #6666AA 1px;
		}
		
		h1
		{
			text-align: center;
			padding: 10px;
		}
		
		h2
		{
			padding: 15px 0 0 0;
		}
		
		h3
		{
			padding: 15px 0 0 5px;
		}
		
		ul
		{
			padding: 5px 0 5px 20px;
			list-style-position: inside;
		}
		
		a
		{
			color: White;
			text-decoration: underline;
		}
		
		a.sharp
		{
			text-decoration: none;
		}
		
		pre
		{
			background-color: #CCCCFF;
			color: Black;
			width: 795px;
			margin: 0 0 5px 42px;
			padding: 4px;
		}
		
		p
		{
			padding: 10px 0 5px 10px;
		}
		
		span.com
		{
			color: #006633;
		}
	</style>

</head>
<body onload="bodyOnLoad();">

<h1>TzParser</h1>

<h2>Table of Contents</h2>

<ul>
	<li>
		<a href='#pres'>Presentation</a>
	</li>
	<li>
		<a href='#bnf'>Writing a parser in TzBNF using TzParser</a>
		<ul>
			<li><a href='#bnfBase'>Syntax and basic rules</a></li>
			<li><a href='#bnfNeed'>Optionality, repetition and checking</a></li>
			<li><a href='#bnfTz'>Special rules (TzRule) and modifiers (TzModif)</a></li>
			<li><a href='#bnfGroup'>Groups</a></li>
			<li><a href='#bnfAST'>Saving into the AST</a></li>
			<li><a href='#bnfEx'>Example</a></li>
		</ul>
	</li>
	<li>
		<a href='#cpp'>Writing a parser in C++ using TzParser, correspondence to the TzBNF</a>
		<ul>
			<li><a href='#cppBase'>Syntax and basic rules</a></li>
			<li><a href='#cppTz'>Special rules (TzRule)</a></li>
			<li><a href='#cppNeed'>Optionality, repetition, checking and modifiers (TzModif)</a></li>
			<li><a href='#cppGroup'>Groups</a></li>
			<li><a href='#cppAST'>Saving into the AST</a></li>
			<li><a href='#cppEx'>Example</a></li>
		</ul>
	</li>
	<li>
		<a href='#use'>Using a parser in C++ created or generated through TzParser</a>
		<ul>
			<li><a href='#useBase'>Basic use</a></li>
			<li><a href='#useStream'>Creating a stream for TzParser</a></li>
			<li><a href='#useAST'>Interfacing an AST library</a></li>
		</ul>
	</li>
	<li>
		<a href='#moreCpp'>How to create advanced rules in C++ ?</a>
	</li>
	<li>
		<a href='#end'>Bugs ? Contact ? Next ?</a>
	</li>
</ul>

<h2><a name="pres" class="sharp">Presentation</a></h2>

<p>
	This documentation is based on the assumption that you already have a basic knowledge of LL parsing and therefore will not describe how a LL parser works.<br />
	If you should need it : <a href="http://fr.wikipedia.org/wiki/Analyse_LL">http://fr.wikipedia.org/wiki/Analyse_LL</a> (French version) and <a href="http://en.wikipedia.org/wiki/LL_parser">http://en.wikipedia.org/wiki/LL_parser</a> (English version).
</p>

<p>
	TzParser is both a LL parsing library in C++ and a software that generates LL parsers in C++.<br />
	This library was created by Salomon BRYS (salomon . brys @ gmail . com) to allow any programmer to easily generate a LL parser that works with any syntax.
</p>

<p>
	The TzParser library is a library which allows the easy creation of a parser in C++ which can be integrated into your application.<br />
	It is derived from the BNF so as to easily create parsers.<br />
	It allows the parsing of a flux in order to get an AST (Abstract Syntaxe Tree) depending on the syntax.
</p>

<p>
	The TzParser software is a software which generates parsing code in C++, using the TzParser library based upon a BNF file.<br />
</p>

<h2><a name="bnf" class="sharp">Writing a parser in TzBNF using TzParser</a></h2>

<h3><a name="bnfBase" class="sharp">Syntax and basic rules</a></h3>

<p>
	The syntax of the TzBNF is very much inspired by the BNF (Bachus Naur Form).<br />
	It allows to describe in a declerative manner the syntaxic rules of a language.<br />
	Here follows an empty <i>test</i> rule :
</p>

<pre>
<span class="com">// Comment here</span>
test	::=
;
<span class="com">/* Comment here */</span>
</pre>

<p>
	TzParser provides a certain number of basic rules that allow the creation of more advanced rules :
</p>

<pre>
<span class="com">/*
  Implicit rules.
*/</span>
'c'         <span class="com">// Parses character c</span>
"hello"     <span class="com">// Parses character string <i>hello</i></span>

<span class="com">/*
  Basic rules.
  Please note that all the Tzparser basic rules start with a capital letter.
*/</span>
GetChar     <span class="com">// Parses any character. Fails only if it is the end of the file</span>
Identifier  <span class="com">// Parses an identifier (a series of letters, digits or underscores which does not start</span>
            <span class="com">// by a digit)</span>
Integer     <span class="com">// Parses an integer</span>
Float       <span class="com">// Parses a float</span>
QuotedPair  <span class="com">// Parses the character \ followed by another simple character. For instance : \n</span>
CInChar     <span class="com">// Parses either a simple character, or a QuotedPair</span>
CChar       <span class="com">// Parses a character in C standards. For instance : 'c', '\n'</span>
CStr        <span class="com">// Parses a character string in C standards. For instance : "Salut le \"monde\" !\n"</span>
EndOfFile   <span class="com">// Fails if the end of the file is not reached</span>
</pre>

<p>
	Let us create an <i>affect</i> rule which shall parse a very simple affectation of an integer in C standards :
</p>

<pre>
<span class="com">// Parses an affectation of the following type : "mavar = 42;"</span>
affect	::=
    Identifier '=' Integer ';'
;
</pre>

<p>
	TzBNF also allows you to create or to concatenate strings.<br />
	Furthermore, TzBNF provides you with several pre-existing strings (Useless at this point, but their utility will be defined later in this chapter). Please note that the [x-y] syntax is not part of TzBNF and is present in this example only for clarity.<br />
	By convention, the names of the strings are written in capital letters.
</p>

<pre>
<span class="com">/*
  Creation strings
*/</span>
NOM = "Salomon";                             <span class="com">// Simple string</span>
BONJOUR = "Bienvenue, " . NOM                <span class="com">// Concatenation</span>
POINT = '.'                                  <span class="com">// Simple string</span>
MESSAGE = BONJOUR . POINT . ' ' . "Ca va ?"  <span class="com">//Concatenation</span>

<span class="com">/*
  Using a string within a rule
*/</span>
Test	::=
    NOM  <span class="com">// Parse "Salomon"</span>
;

<span class="com">/*
  Standard string definied by TzBNF
*/</span>
P_HT       = '\t';                   <span class="com">// Tab</span>
P_SP       = ' ';                    <span class="com">// Space</span>
P_LBLANKS  = P_HT . P_SP;            <span class="com">// Linear blank characters</span>

P_CR       = '\r';                   <span class="com">// Carriage return</span>
P_LF       = '\n';                   <span class="com">// New line under Unix</span>
P_CRLF     = P_CR . P_LF;            <span class="com">// New line under Windows</span>
P_NL       = P_CRLF;                 <span class="com">// P_CRLF alias</span>

P_BLANKS   = P_LBLANKS . P_CRLF;     <span class="com">// Blank characters</span>

P_UPALPHA  = [A-Z];                  <span class="com">// Capital letters</span>
P_LOALPHA  = [a-z];                  <span class="com">// small letters</span>
P_ALPHA    = P_UPALPHA . P_LOALPHA;  <span class="com">// Capital and small letters</span>

P_NUM      = [0-9];                   <span class="com">// Digits</span>
P_DIGIT    = P_NUM;                  <span class="com">// P_NUM alias</span>

P_ALPHANUM = P_ALPHA . P_NUM;        <span class="com">// Alphabet and digits</span>

P_CTL      = [...];                  <span class="com">// Any control ASCII character : from 1 to 31 and 127</span>

P_TEXT     = [...];                  <span class="com">// Any text ASCII character : from 32 to 126</span>

P_CHAR     = P_CTL . P_TEXT;         <span class="com">// Any ASCII character except 0</span>

P_HEX      = "ABCDEF" . P_NUM;       <span class="com">// Hexadecimal characters</span>
</pre>

<h3><a name="bnfNeed" class="sharp">Optionality, repetition and checking</a></h3>

<p>
	Certain rules can be optional or repetitive.<br />
	TzBNF allows the easy management of Optionality or repetition of a rule (N represents the infinite) :
</p>

<pre>
<span class="com">/*
  Simple indicators.
*/</span>
regle?          <span class="com">// Parses the rule 0 or 1 time</span>
regle*          <span class="com">// Parses the rule from 0 to N time(s)</span>
regle+          <span class="com">// Parses the rule from 1 to N time(s)</span>

<span class="com">/*
  Advanced indicators.
  In the following examples, the characters in between commas and braces are given for the purpose
  of the example.
*/</span>
regle{2}        <span class="com">// Parses the rule twice</span>
regle{+}        <span class="com">// Parses the rule from 1 to N time(s), the equivalent of regle+</span>
regle{+, '-'}   <span class="com">// Parses the rule from 1 to N time(s), separated by '-' characters</span>
regle{2, '-'}   <span class="com">// Parses the rule twice, separated by '-' characters</span>
regle{,}        <span class="com">// Parses the rule from 0 to N time(s), the equivalent of regle* : no min or max,</span>
                <span class="com">// the equivalent of regle{0,0}</span>
regle{2,}       <span class="com">// Parses the rule from 2 to N time(s), the equivalent of regle{2,0}</span>
regle{,4}       <span class="com">// Parses the rule from 0 to 4 time(s), the equivalent of regle{0,4}</span>
regle{2,4}      <span class="com">// Parses the rule from 2 to 4 time(s)</span>
regle{,,'-'}    <span class="com">// Parses the rule from 0 to N time(s), separated by '-' characters, the equivalent</span>
                <span class="com">// of regle{*,'-'}, also of regle{0,0,'-'}</span>
regle{2,,'-'}   <span class="com">// Parses the rule from 2 to N time(s), separated by '-' characters, the equivalent</span>
                <span class="com">// of regle{2,0,'-'}</span>
regle{,4,'-'}   <span class="com">// Parses the rule from 0 to 4 time(s), separated by '-' characters, the equivalent</span>
                <span class="com">// of regle{0,4,'-'}</span>
regle{2,4,'-'}  <span class="com">// Parses the rule from 2 to 4 time(s), separated by '-' characters</span>
</pre>

<p>
	Let us go back to the <i>affect</i> rule and make it so that it can also parse an affectation upon creation :
</p>

<pre>
<span class="com">// Parses an affectation of the type "mavar = 42;" or "int mavar = 42;"</span>
<span class="com">// We admit that the rule <i>type</i> has already been created</span>
affect	::=
    type? Identifier '=' Integer ';'
;
</pre>

<p>
	The TzBNF allows you to check a rule without consuming it.<br />
	If the rule is preceded by the character '=', TzParser will parse but will not consume the rule.<br />
	That is to say that the rule will fail if it is not parsed and the following rule will start at the same point as the checked rule (and not following it).<br />
	If the rule is preceded by the character '!', TzParser will check that the rule IS NOT parsed.<br />
	This behaviour allows you to check for certain particular cases and to optimize your parser to check a simple generic rule before entering a more complex rule.
</p>

<pre>
Identifier =Float      <span class="com">// Tests the rule which parses an identifier and checks if it is followed by</span>
                       <span class="com">// a float without consuming the float</span>

Identifier !Float{2,}  <span class="com">// Tests the rule which parses an identifier and checks that it is not</span>
                       <span class="com">// followed by at least two floats</span>  
</pre>

<h3><a name="bnfTz" class="sharp">Special rules (TzRule) and modifiers (TzModif)</a></h3>

<p>
	The TzBNF includes a set of special rules which can take arguments.<br />
	Those rules start with the character '#'.<br />
	The arguments are of a litteral type (that is to say a 'c'haracter, a "string", a "conc"."atenation" or the name of a string), boolean (+ for true and - for false) or eventually NULL (0).
</p>

<pre>
<span class="com">/*
  #GetChar can take 0, 1, 2 or 3 arguments
  arg 1 : Optional boolean, + if the GetChar is to be insensible to case, - (default) otherwise
  arg 2 : Litteral or NULL, character or character string representing a list of characters to be
          parsed
  arg 3 : Litteral, character or character string representing a list of characters not to be parsed
*/</span>
#GetChar()                 <span class="com">// The equivalent of GetChar</span>
#GetChar(P_ALPHA)          <span class="com">// Parses any character in P_ALPHA</span>
#GetChar(+, P_LOWALPHA)    <span class="com">// Parses from 1 to N time(s) the equivalent of the previous example</span>
                           <span class="com">// because it is insensible to case</span>
#GetChar(P_NUM, '0')       <span class="com">// Parses any character in P_NUM but 0</span>
#GetChar(+, P_HEX, P_NUM)  <span class="com">// Parses from 1 to N time(s) any character in P_HEX but for those in</span>
                           <span class="com">// P_NUM while not respecting case (takes into account upper AND lower</span>
  			   <span class="com">// case)</span>
#GetChar("ABCDEFabcdef")   <span class="com">// The equivalent of the previous example</span>
#GetChar(+, 0, P_NUM)      <span class="com">// Parses from 1 to N time(s) any character that is not in P_NUM</span>

<span class="com">/*
  <i>#ReadUntil</i> takes a litteral as an argument
  Keeps on parsing until it encounters this string or it fails if the end of the file is reached
*/</span>
"/*" #ReadUntil("*/")      <span class="com">// Parses a C comment : parses from <span class="com">/* to the first */</span></span>

<span class="com">/*
  <i>#Identifier</i> can take 0 or 1 boolean argument
  If the argument is -, an identifier will be parsed while allowing the first character to be a
  digit
*/</span>
#Identifier                <span class="com">// The equivalent of <i>Identifier</i></span>
#Identifier(+)             <span class="com">// The equivalent of <i>Identifier</i> (+ is the default value)</span>
#Identifier(-)             <span class="com">// Parses an identifier without checking the first character</span>
                           <span class="com">// WARNING : This instruction parses 42coucou21</span>
                           <span class="com">//             but also any positive integer such as 4221</span>

<span class="com">/*
  <i>#Integer</i> can take 0 or 1 boolean argument
   If it is defined, the first argument defines if the integer is to be positive or negative.
*/</span>
#Integer                   <span class="com">// The equivalent of <i>Integer</i></span>
#Integer(+)                <span class="com">// Parses a positive integer such as 2142</span>
#Integer(-)                <span class="com">// Parses a negative integer such as -84</span>

<span class="com">/*
  <i>#Float</i> can take 0, 1 or 2 arguments
  arg 1 : Optional boolean, just like <i>#integer</i>, defines if the float is to be positive or negative
  arg 2 : Optional character, defines the character used as a decimal point, default is '.'
*/</span>
#Float                     <span class="com">// The equivalent of <i>Float</i></span>
#Float(-)                  <span class="com">// Parses a negative float, such as -21.42</span>
#Float(',')                <span class="com">// Parses a float with ',' as a decimal point</span>
                           <span class="com">//   For instance : 21,42 or -21,42</span>
#Float(+, ',')             <span class="com">// Parses a positive float with ',' as a decimal point</span>
                           <span class="com">//  For instance : 21,42</span>
</pre>

<p>
	The TzBNF includes a few modifiers which allow the modification of the behaviour of a rule.
</p>

<pre>
<span class="com">/*
  >Ignore() allows to ignore all the characters of a string or anything that will be parsed by a
  given rule
*/</span>
>Ignore(LBLANKS) declaration  <span class="com">// Parses the <i>declaration</i> rule in which all the linear blank</span>
                              <span class="com">// characters will be ignored</span>
>Ignore(CIgnore) declaration  <span class="com">// Parses the <i>declaration</i> rule in which all that is parsed</span>
                              <span class="com">//    by the <i>CIgnore</i> rule (already defined) will be ignored</span>
>Ignore() declaration         <span class="com">// Parses the <i>declaration</i> rule taking everything into account </span>
                              <span class="com">// (overrides the <i>ignore</i> for this rule if it is defined by the caller</span>
                              <span class="com">// rule)</span>

<span class="com">/*
  >NoIgnore will not parse the <i>ignore</i> rule before the given rule.
  WARNING : This rule is VERY different from >Ignore(). If you wish to take everything into account
            WITHIN the rule, you must use >Ignore(), whereas if you wish to take everything into
            account BEFORE the rule, you must use >NoIgnore 
*/</span>
declaration >NoIgnore ';'     <span class="com">// Parses the <i>declaration</i> rulefollowed by the character ';' WITHOUT</span>
                              <span class="com">// ignoring anything defined previously in between the declaration</span>
			      <span class="com">// and the character ';'</span>	
<span class="com">/*
  >Force() forces the rule to succeed, and it generates a parse error if the rule fails.
  It takes as a parameter the string which will be used as the text of the parse error.
*/</span>
>Force("EOF !!!") EndOfFile   <span class="com">// Generates a parse error if it is not the end of the file</span>
</pre>

<h3><a name="bnfGroup" class="sharp">Groups</a></h3>

<p>
	The TzBNF allows the regrouping of rules into groups using the characters [].<br />
	Those groups also allow the parsing of a certain rule instead of others by using the character |.<br />
	A group is a rule itself, just like any other, and as such, it can be assigned anything that can be assigned to other rules.
</p>

<pre>
<span class="com">/*
  Test1 rule which parses an Identifier followed by an unknown number of ',' Identifier
  The equivalent of Identifier{+, ','}
*/</span>
Test1	::=
    Identifier
    [ ',' Identifier]*
;

<span class="com">/*
  Test2 rule which parses either an Integer or a Float.
  Please note that the group MUST be in that precise order since Float has the ability
  to parse an Integer => A float does not necessarily have a decimal point
*/</span>
Test2	::=
    [ Float | Integer ]
;
</pre>

<h3><a name="bnfAST" class="sharp">Saving into the AST</a></h3>

<p>
	Tzparser's ASt system is based upon XML.<br />
	Even though you can (see lower down) interface any system (XML or not), the principle is still based upon XML and this documentation is only concerned with the AST in XML form.<br />
	In the TzBNF, there are two possible ways of saving into the tree : Creating a node child of the previous one or creating an attribute within the previous node.
</p>

<pre>
regle:id            <span class="com">// Parses the rule, creates an <i>id</i> node and saves what has been parsed</span>
                    <span class="com">// into the <i>value</i> attribute of the newly created node</span>
regle:!id           <span class="com">// Parses the rule and creates an <i>id</i> node without saving what has been parsed</span>
regle:id.           <span class="com">// Parses the rule, creates an <i>id</i> node, saves what has been parsed and saves</span>
                    <span class="com">// the current line into the <i>Line</i> attribute of the newly created node</span>
regle:!id.          <span class="com">// Parses the rule, creates an <i>id</i> node without saving what has been parsed and</span>
                    <span class="com">// saves the current line in the <i>Line</i> attribute of the newly created node</span>
regle:&lt;idval&gt;       <span class="com">// Parses the rule and saves what has been parsed into the <i>idval</i> attribute of</span>
                    <span class="com">// the previous node</span>
regle:&lt;type "id"&gt;   <span class="com">// Parses the rule and creates a <i>type</i> attribute with <i>id</i> as a value in the</span>
                    <span class="com">// previous node. Please note that any character, string, concatenation, or name</span>
                    <span class="com">// of a string could have been used instead of "id".</span>
regle:id:&lt;type "id"&gt;<span class="com">// Parses the rule, creates a <i>type</i> attribute with <i>id</i> as a value in the previous</span>
                    <span class="com">// node, then creates a new <i>id</i> node, saves what has been parsed in the newly</span>
                    <span class="com">// created node.</span>
</pre>

<h3><a name="bnfEx" class="sharp">Example</a></h3>

<p>
	Here comes an example using all the afore-mentionned notions :
</p>

<pre>
Test		::=
    Prec*
    Check?:!Check
    >Ignore(P_LBLANKS)
    [
        In:&ltpoint '1'&gt; ='.'
    |
        In:&ltpoint '0'&gt;
    ]:In
    >NoIgnore After?
;
</pre>

<p>
	Creates a <i>Test</i> rule, which parses from 0 to N <i>Prec</i> then 0 or 1 <i>Check</i>.<br />
	If this <i>Check</i> is parsed, a <i>Check</i> node is created without a <i>value</i> attribute (knowing that all the attributes that will be defined WITHIN this rule will be saved in this attribute if no other node has been defined).<br />
	Then it parses EITHER a In followed by a dot, without consuming this dot, OR an In, while ignoring all the linear blank characters.<br />
	Please pay close attention to the order in which the group is defined. If the simple In had been put first, the dot would never had been parsed since the simple In rule would have succeeded even if it was still followed by a dot.<br />
	An In node is created, which contains a <i>value</i> attribute, itself containing what has been parsed in the group, and a <i>point</i> attribute which contains either '0' or '1' depending on what has been parsed.<br />
	Finally, the <i>After</i> may be parsed (which will parse the character '.', if it is present) without ignoring anything between the group and the itself.
</p>

<h2><a name="cpp" class="sharp">Writing a parser in C++ using TzParser, correspondence to the TzBNF</a></h2>

<h3><a name="cppbase" class="sharp">Syntax and basic rules</a></h3>

<p>
	A parser using TzParser uses 2 files : a .h in which the rules and the strings are declared, and a .cpp in which the rules are implemented.<br />
	See below for how to define a rule and a string in a .h (Please note that the strings are just plain <i>define</i>, and also that the CONCAT macros can be used directly in the code and that they exist up to CONCAT15) :
</p>

<pre>
RULE_DECLARE_SIMPLE(Test);                 <span class="com">// Definition of the <i>Test</i> rule</span>

#define MYSTR     "coucou"                 <span class="com">// Definition of the MYSTR string</span>
#define MYCONCAT  CONCAT3("to", "-", "ma") <span class="com">// Definition of the MYCONCAT string set to "to-ma"</span>
</pre>

<p>
	The syntax of the TzParser in C++ was created to ressemble as much as possible that of the TzBNF, so that it would be easily transcribable, so this chapter will focus on how to go from TzBNF to C++, which is what the TzParser generator does.<br />
	However, as is often the case, the syntax of C++ allows more freedom, which we shall see at the end of the chapter, in the advanced rules section.<br />
	See below for how to implement the <i>Test</i> rule declared higher up, which parses an Identifier followed by a Float :
</p>

<pre>
RULE_IMPLEMENT(Test, p)       <span class="com">// arg1: Name of the rule, arg2: parser variable (p par convention)</span>
{
    p   >>  Identifier().r()  <span class="com">// Parses an Identifier. Uses the variable defined higher up.</span>
        >>  Float().r()       <span class="com">// Parses a Float</span>
        ;
    RULE_RETURN(p);           <span class="com">// Return of the rule</span>
}
</pre>

<p>
	Please note that the .r() which follows Identifier() and Float() is not mandatory when compiling with Visual Studio.<br />
	This .r() corrects a G++ aberration (reference to the instantiation) and it is written by default upon generation to insure cross-compatibility (r() only does { return *this; } ).
</p>

<p>
	Here follow the basic rules and their equivalents in TzBNF (strings being #define, they can be used just as in TzBNF) :
</p>

<pre>
<span class="com">/*
  Implicit rules
*/</span>
GetChar().only('c')  <span class="com">// => 'c'</span>
Read().str("hello")  <span class="com">// => "hello"</span>

<span class="com">/*
  Basic rules
*/</span>
GetChar()        <span class="com">// => GetChar</span>
Identifier()     <span class="com">// => Identifier</span>
Integer()        <span class="com">// => Integer</span>
Float()          <span class="com">// => Float</span>
QuotedPair()     <span class="com">// => QuotedPair</span>
CInChar()        <span class="com">// => CInChar</span>
CChar()          <span class="com">// => CChar</span>
CStr()           <span class="com">// => CStr</span>
EndOfFile()      <span class="com">// => EndOfFile</span>
</pre>

<h3><a name="cppTz" class="sharp">Special rules (TzRule)</a></h3>

<p>
	All the rules in the TzParser have a few modifiers (We will see the common ones later on).<br />
	In addition to the common modifiers, the TzRule (rules which names begin with a #) correspond in C++ to rules which have their own modifiers.<br />
	The modifiers can be chained.
</p>

<pre>
<span class="com">/*
  #GetChar :
  arg 1 : Boolean : .caseInsensitive()
  arg 2 : Literal : .only() for a character OR .in() for a character string
  arg 3 : Literal : .but() for a character OR .notIn() for a character string
*/</span>
GetChar()                                  <span class="com">// => GetChar</span>
GetChar().in(P_LBLANKS)                    <span class="com">// => #GetChar(P_LBLANKS)</span>
GetChar().in(P_NUM).but('0')               <span class="com">// => #GetChar(P_NUM, '0')</span>
GetChar().notIn(P_NUM)                     <span class="com">// => #GetChar(0, P_NUM)</span>
GetChar().in(P_HEX).caseInsensitive(true)  <span class="com">// => #GetChar(+, P_HEX)</span>

<span class="com">/*
  #ReadUntil :
*/</span>
Read().until("*/")                         <span class="com">// => #ReadUntil("*/")</span>

<span class="com">/*
  #Identifier :
  arg 1 : Booleen : .checkFirstChar()
*/</span>
Identifier()                               <span class="com">// => Identifier</span>
Identifier().checkFirstChar(false)         <span class="com">// => #Identifier(-)</span>

<span class="com">/*
  #Integer :
  arg 1 : Booleen : .forcePositive() si +, .forceNegative() si -
*/</span>
Integer()                                  <span class="com">// => Integer</span>
Integer().forcePositive()                  <span class="com">// => #Integer(+)</span>
Integer().forceNegative()                  <span class="com">// => #Integer(-)</span>

<span class="com">/*
  #Float :
  arg 1 : Booleen : .forcePositive() si +, .forceNegative() si -
  arg 2 : Caractere : .coma()
*/</span>
Float()                                    <span class="com">// => Float</span>
Float().forcePositive()                    <span class="com">// => #Float(+)</span>
Float().forceNegative()                    <span class="com">// => #Float(-)</span>
Float().coma(',')                          <span class="com">// => #Float(',')</span>
Float().forcePositive().coma(',')          <span class="com">// => #Float(+, ',')</span>
</pre>

<h3><a name="cppNeed" class="sharp">Optionality, repetition, checking and modifiers (TzModif)</a></h3>

<p>
	In the TzParser syntax, any operation with the aim of modifying the behaviour of a rule uses a modifier.<br />
	The following modifiers are common to all the rules (including user-defined ones).<br />
	These modifiers MUST be called AFTER the potential rule-specific modifiers.<br />
</p>

<pre>
<span class="com">/*
  The optionality and the repetition (handled by the characters '?', '*' and '+' in TzBNF, are
  handled by the modifier .n() in C++.
  This modifier can use the TzBNF character, a <i>define</i> corresponding to the TzBNF character,
  or a minimum and a maximum. For each call, a potential space character can be specified as the
  last argument.
  ? (= PARSE_ZERO_OR_ONE = PARSE_ZOO), + (= PARSE_ONE_OR_MORE = PARSE_OOM) and * (= PARSE_ANY)
*/</span>
Regle().n('+')                 <span class="com">// => Regle+</span>
Regle().n(PARSE_OOM)           <span class="com">// => Regle+</span>
Regle().n(2, 4)                <span class="com">// => Regle{2, 4}</span>
Regle().n(2, 0)                <span class="com">// => Regle{2,}</span>
Regle().n(2, 2)                <span class="com">// => Regle{2}</span>
Regle().n('+', '-')            <span class="com">// => Regle{+, '-'}</span>
Regle().n(2, 0, '-')           <span class="com">// => Regle{2,,'-'}</span>

<span class="com">/*
  The checking is done using the modifier <i>.check()</i>.
  <i>check</i> takes a boolean as a parameter, which defines whether you wish to check for the presence or
  the absence of a rule.
*/</span>
Regle().check(true)            <span class="com">// => =Regle</span>
Regle().check(false)           <span class="com">// => !Regle</span>

<span class="com">/*
  The TzBNF modifier <i>>Ignore()</i> corresponds to the C++ modifier <i>ignore()</i>.
  WARNING : If <i>ignore</i> has the name of a rule as a parameter, do not forget the brackets !
*/</span>
Regle().ignore()               <span class="com">// => >Ignore() Regle</span>
Regle().ignore(P_LBLANKS)      <span class="com">// => >Ignore(P_LBLANKS) Regle</span>
Regle().ignore(RegleIgnore())  <span class="com">// => >Ignore(RegleIgnore) Regle</span>

<span class="com">/*
  The TzBNF modifier <i>>NoIgnore</i> corresponds to the C++ modifier <i>ignoreBefore(false)</i>.
  You can call <i>ignoreBefore(true)</i> if you are handling a rule on which <i>ignoreBefore(false)</i>
  has been (or could be) called so as to cancel its effect and restate that the rule will parse the
  <i>ignore</i> before it is parsed.
*/</span>
Regle().ignoreBefore(false);   <span class="com">// => >NoIgnore Regle</span>

<span class="com">/*
  The TzBNF modifier <i>>Force()</i> corresponds to the C++ modifier <i>force()</i>.
  <i>force()</i> can be called without any argument if you want to cancel the <i>force</i> on a rule.
*/</span>
Regle().force("ouch !")        <span class="com">// => >Force("ouch !") Regle</span>
</pre>

<h3><a name="cppGroup" class="sharp">Groups</a></h3>

<p>
	There are two types of groups : the simple group AND and the conditionnal group OR.<br />
	The OR group tests each of its members and stops at the first success, which means that if one member contains more than one rule, the type of group used should be AND.
</p>

<pre>
<span class="com">/*
  test1       ::=
      [Identifier float]*
  ;
*/</span>
RULE_IMPLEMENT(test1, p)
{
    p   >>  ( G_AND
            >>  Identifier().r()
            >>  Float().r()
            ).n('*').r()              <span class="com">// Please notice the modifiers after the closing of the group</span>
        ;
    RULE_RETURN(p);
}

<span class="com">/*
  test2       ::=
      [truc | machin]
  ;
*/</span>
RULE_IMPLEMENT(test2, p)
{
    p   >>  ( G_OR
            >>  truc().r()
            >>  machin().r()
            ).r()
        ;
    RULE_RETURN(p);
}

<span class="com">/*
  test3       ::=
      [truc | Identifier float | machin]*
  ;
*/</span>
RULE_IMPLEMENT(test3, p)
{
    p   >>  ( G_OR
            >>  truc().r()
            >>  ( G_AND               <span class="com">// Please notice the creation of the AND group</span>
                >>  Identifier().r()
                >>  Float().r()
                ).r()
            >>  machin().r()
            ).n('*').r()
        ;
    RULE_RETURN(p);
}
</pre>

<h3><a name="cppAST" class="sharp">Saving into the AST</a></h3>

<p>
	As for the rest, saving into the ASt is also done using modifiers.
</p>

<pre>
Regle().saveNode("noeud")                                     <span class="com">// => Regle:noeud</span>
Regle().saveNode("noeud", false)                              <span class="com">// => Regle:!noeud</span>
Regle().saveNode("noeud").saveLine()                          <span class="com">// => Regle:noeud.</span>
Regle().saveAttr("attr")                                      <span class="com">// => Regle:&lt;attr&gt;</span>
Regle().saveAttr("attr", "val")                               <span class="com">// => Regle:&lt;attr "val"&gt;</span>
Regle().saveNode("noeud", false).saveLine().saveAttr("attr")  <span class="com">// => Regle:!noeud.:&lt;attr&gt;</span>
</pre>

<h3><a name="cppEx" class="sharp">Example</a></h3>

<p>
	Let us reconsider the TzBNF example of the previous chapter and transcribe it into C++ :
</p>

<pre>
<span class="com">/*
  Test		::=
      Prec*
      Check?:!Check
      >Ignore(P_LBLANKS)
      [
          In:&ltpoint '1'&gt; ='.'
      |
          In:&ltpoint '0'&gt;
      ]:In
      >NoIgnore After?
  ;
*/</span>

RULE_IMPLEMENT(Test, p)  <span class="com">// WARNING : Do not forget <i>RULE_DECLARE_SIMPLE(Test);</i> in the .h file</span>
{
    p   >>  Prec().n('*').r()
        >>  Check().n('?').saveNode("Check", false).r()
        >>  ( G_OR
            >> ( G_AND
                >>  In().saveAttr("point", "1").r()
                >>  GetChar().only('.').check(true).r()
                ).r()
            >>  In().saveAttr("point", "0").r()
            ).ignore(P_LBLANKS).saveNode("In").r()
        >>  After().n('?').ignoreBefore(false).r()
        ;
    RULE_RETURN(p);
}
</pre>

<p>
	Even though it is hard to decypher, this syntax is just as simple as that of the TzBNF.<br />
	It will come in handy when writing more advanced parsers which will need C++ code directly when using advanced functionalities of TzParser (See the dedicated chapter lower down).
</p>

<h2><a name='use' class="sharp">Using a parser in C++ created or generated through TzParser</a></h2>

<h3><a name='useBase' class="sharp">Basic use</a></h3>

<p>
	It is useless to parse a flux if not to obtain an AST.<br />
	TzParser does not provide an AST system but an interface which allows the interfacing of just any ASt system.<br />
	TzParser comes with the adapter which allows the use of <a href="http://www.grinninglizard.com/tinyxml/">TinyXML</a> as an AST library.<br />
	Here follows an example (with comments) on how to use TzParser in a C++ program (We assume that Rules.h and Rules.cpp are the files of the TzParser rules, and that TRACE is a <i>define</i> for true or false) :
</p>

<pre>
#include "tzParse/tzParse.h"             <span class="com">// We include the tzParse library</span>

#include "tzParse/ASTAdapt/TzTinyXML.h"  <span class="com">// We include the AST adapter for TinyXML</span>
                                         <span class="com">// (which does include TinyXML)</span>

#include "Rules.h"                       <span class="com">// We include the header for the rules</span>

using namespace tzParse;                 <span class="com">// Allows easy access to the parser</span>

int	main()
{
    try
    {
        Parser              p;           <span class="com">// The parser is created</span>
        TzTinyXMLDocument   d;           <span class="com">// The TinyXML document, adapted to the AST system,</span>
					 <span class="com">// is created</span>

        p.setXMLDoc(&d);                 <span class="com">// The document to be filled-in is defined to the parser</span>

        if (TRACE)
            p.trace();                   <span class="com">// The route of the parser is potentially traced</span>
                                         <span class="com">// WARNING : VERY wordy and VERY slow (the HARD way)</span>

        ifstream    f("masyntaxe.txt");  <span class="com">// The file to be parsed is opened</span>

        p   <<  f;                       <span class="com">// The flux is inserted in the parser</span>

        p   >>  RegleBase().r();         <span class="com">// The <i>RegleBase</i> rule is parsed</span>

        <span class="com">/*
          The next few lines of code are specific to TinyXML and allow the displaying
          of the XML tree.
        */</span>
        {
            TiXmlPrinter    printer;
            printer.SetIndent( "    " );
            d.Accept(&printer);
            cout << printer.CStr();
        }
    }

    catch (std::exception& e)            <span class="com">// The TinyXML and TzParse exceptions inherit the</span>
                                         <span class="com">// std::exception</span>
    {
        cout << e.what() << endl;
    }

    return 0;
}
</pre>

<h3><a name='useStream' class="sharp">Creating a stream for TzParser</a></h3>

<p>
	Please notice the instruction (in the previous example) p << f; in which f is an ifstream.<br />
	The insertion of a flux in a TzParser can take any istream as a parameter, or any object inherited from IParseData.<br />
	See below the IParseData interface (defined in IParseData.h) which allows you to create your own flux to be parsed :	
</p>

<pre>
class IParseData
{
public:
    <span class="com">/*
      Method to be overloaded, which returns the next character to be read.
    */</span>
    virtual char    getChar(void) = 0;

    <span class="com">/*
      Method to be overloaded, which returns true if the flux is empty, or false if there are still
      characters to be read.
    */</span>
    virtual bool    isEndOfFile(void) = 0;

    virtual ~IParseData() {};  <span class="com">// Virtual Destroyer</span>
};
</pre>

<p>
	WARNING : The IParseData must behave like the <i>istream</i> as far as the end of the file is concerned, that is to say that isEndOfFile must return true only after getChar returned an "end of file character" (usually -1, but not necessarily) which will be ignored by the parser.
</p>

<h3><a name='useAST' class="sharp">Interfacing an AST library</a></h3>

<p>
	TzParser allows the use of just any library (XML or not) which, once it has been properly interfaced, provides a document that can be filled with what has been parsed by Tzparser.<br />
	However, even though it is possible to use systems other than XML, TzParser will use those libraries as though they were XML libraries.<br />
	See below the 2 interfaces to be overloaded in order to interface a library for the AST :
</p>

<pre>
class IParseASTElement
{
public:
    <span class="com">/*
      Method to be overloaded which takes an IParseASTElement* as a parameter. This parameter
      MUST come from the class returned by IParseASTDocument::createElement, so you can easily
      downcast it using dynamic_cast.
      ATTENTION : If you copy <i>child</i>, then you must delete it <i>(delete child)</i>;
    */</span>
    virtual void    addChild(IParseASTElement* child) = 0;

    <span class="com">/*
      Adds an argument to the element
    */</span>
    virtual void    setAttribute(const std::string& name, const std::string& value) = 0;

    virtual ~TzTinyXMLElement() {}  <span class="com">// Virtual Destroyer</span>
};

class IParseASTDocument
{
public:
    <span class="com">/*
      Same method as IParseASTElement::addChild.
    */</span>
    virtual void                addChild(IParseASTElement*) = 0;

    <span class="com">/*
      Creates an element which can be added to the document or to another element through the use
      of <i>addChild</i>.
    */</span>
    virtual IParseASTElement*   createElement(const std::string& name) = 0;

    virtual ~TzTinyXMLDocument() {}  <span class="com">// Virtual Destroyer</span>
};
</pre>

<p>
	In order to understand fully the process of creation of an ASt adapter, we strongly advise that you take a look at the file ASTAdapt/TzTinyXML.h which adapts the TinyXML library very easily.
</p>

<h2><a name="moreCPP" class="sharp">How to create advanced rules in C++</a></h2>

<p>
	The TzParser library allows the creation of advanced rules, that is to say rules, just like GetChar, with specific modifiers.<br />
	WARNING : For the moment it is not possible to use such rules in a parser written in TzNBNF. If you decide to use advanced rules, you must (for the moment) write your whole parser in C++.
</p>

<p>
    The definition ofthe modifiers is done in the .h file. Instead of RULE_DECLARE_SIMPLE, see below how to declare an advanced rule (named <i>Test</i>) :
</p>

<pre>
RULE_DECLARE_HEAD(Test)                          <span class="com">// Class signature</span>
{
    RULE_HEAD(Test);                             <span class="com">// Mandatory : implements the builders</span>
    RULE_SIMPLE_CLONE(Test);                     <span class="com">// Mandatory : implements the clone method</span>

    RULE_NO_TRACE();                             <span class="com">// WRITE THIS ONLY IF YOU DO NOT WISH THE RULE TO</span>
                                                 <span class="com">// DISPLAY IN THE TRACE</span>

    RULE_ARG(_a, bool, false);                   <span class="com">// Creates a bool _a attribute (set by default to</span>
						 <span class="com">// false)</span>
    RULE_METHARG_DEF(Test, a1, _a, bool, true);  <span class="com">// Creates a modifier a1 set to _a and which</span>
                                                 <span class="com">// argument is optional (set by default to true)</span>
    RULE_METHARG(Test, a2, _a, bool);            <span class="com">// Creates a modifier a2 set to _a</span>

    RULE_ARGNULL(_b, char*);                     <span class="com">// Creates a char* _b attribute (set by default to</span>
						 <span class="com">// NULL)</span>
                                                 <span class="com">// WARNING : To format pointers to NULL, you must</span>
                                                 <span class="com">// use RULE_ARGNULL because RULE_ARG(_a, char*, 0)</span>
                                                 <span class="com">// does not work under G++...</span>
    RULE_METHARG(Test, b, _b, char*);            <span class="com">// Creates a modifier b set to _b</span>

    RULE_STDARG(Test, c, char, '1');             <span class="com">// The equivalent of (Please note the added</span>
						 <span class="com">//  underscore) :</span>
                                                 <span class="com">//   RULE_ARG(_c, char, '1');</span>
                                                 <span class="com">//   RULE_METHARG(Test, c, _c, char);</span>

    RULE_STDARG_DEF(Test, d, char, '1', '2');    <span class="com">// The equivalent of (Please note the added</span>
						 <span class="com">//  underscore) :</span>
                                                 <span class="com">//   RULE_ARG(_d, char, '1');</span>
                                                 <span class="com">//   RULE_METHARG_DEF(Test, d, _d, char, '2');</span>

    RULE_STDARGNULL(Test, e, const char*);       <span class="com">// The equivalent of (Please note the added</span>
						 <span class="com">//  underscore) :</span>
                                                 <span class="com">//   RULE_ARGNULL(_e, const char*);</span>
                                                 <span class="com">//   RULE_METHARG(Test, e, _e, const char*);</span>

    RULE_STDARGNULL_DEF(Test, f, char*, "abc");  <span class="com">// The equivalent of (Please note the added</span>
						 <span class="com">//  underscore) :</span>
                                                 <span class="com">//   RULE_ARGNULL(_f, char*);</span>
                                                 <span class="com">//   RULE_METHARG_DEF(Test, f, _f, char*, "abc");</span>

};                                               <span class="com">// Please note the ';' (It is a class)</span>
</pre>

<p>
	Please note that RULE_ARG, RULE_ARGNULL, RULE_METHARG and RULE_METHARG_DEF are rarely used, RULE_STDARG, RULE_STDARG_DEF, RULE_STDARGNULL et RULE_STDARGNULL_DEF being used instead. Those, in addition to declaring the attributes, implements their modifiers.<br/>
	Once inside RULE_IMPLEMENT, the operator * must be used to access the arguments. For instance, to access the char _d value of the previous example, *_d must be used. This is explained by the fact that it is not a char which is created but an AutoInit&lt;char, '1'&gt;.<br/>
	To understand fully the way the advanced rules work, please take a look at the TzParseDefaultRules.h and TzParseDefaultRules.cpp files containing the default rules of TzParser (many are relatively simple advanced rules).
</p>

<h2><a name="end" class="sharp">Bugs ? Contact ? Next ?</a></h2>

<p>
	In case you would find a bug, please go to the project bugtracker.
</p>

<p>
	In case you would have trouble understanding something or need help, you are invited to go to the project forum where I will try to answer your questions ASAP.<br />
	If you wish to contact me, please do not hesitate to do so (in French or in English) : salomon . brys @ gmail . com
</p>

<p>
	To see or propose any coming functionality, please go to the project's wishList.
</p>

<p>
	TzParser is under a FREE licence if your project is FREE (which does not necessarily mean open-source) and under a COMMERCIAL licence if your project is COMMERCIAL (which does not necessarily mean close-source).
	Each of the 2 licences have particularities, so please consult the LICENCE.txt file if you wish to use TzParser in your project.
</p>

<p></p>
<p></p>

<p><FONT face="Times New Roman" size=3><center<u>Translated from French by Brice Damien (<a href="mailto:brice.damien@tele2.fr">brice.damien@tele2.fr</a>), 2008</u></p>


</body>
</html>
